package com.candoit.webapps.pricing.util.spreadsheet;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.candoit.webapps.pricing.model.Categoria;
import com.candoit.webapps.pricing.model.CentroCostos;
import com.candoit.webapps.pricing.model.CriterioDistribucion;
import com.candoit.webapps.pricing.model.Cuenta;
import com.candoit.webapps.pricing.model.CuentaMes;
import com.candoit.webapps.pricing.util.QueryUtil;

public class CommandSalariesForSpreadsheet {
	
	private Map<CriterioDistribucion, Map<CentroCostos, Double>> matriz_proporcion_criterio_cc;

	/*
	 * Clave: Centros de Costos Productivos
	 * Valor: Objeto que contine Mapa( Clave: centros de costos PPD, Valor: salario distribuido) y la suma 
	 * de los salarios distribuidos del mapa
	 */
	private Map<CentroCostos, CommandDistribucionEnCCPPDporCC> ccppdCosto;
	
	/*
	 * Clave: Centros de Costos Productivos
	 * Valor: Salario total de cada Centro
	 */
	private Map <CentroCostos,Double> salariosCCP;
	
	/*
	 * Clave: Centros de Costos Para-Productivos Directos
	 * Valor: Salario total de cada Centro
	 */
	private Map <CentroCostos,Double> salariosCCPPD;
	
	/*
	 * Centros de Costos Productivos
	 */
	private List<CentroCostos> centros;
	
	
	public CommandSalariesForSpreadsheet(Map<CriterioDistribucion, Map<CentroCostos, Double>> matriz_proporcion_criterio_cc){
		this.matriz_proporcion_criterio_cc = matriz_proporcion_criterio_cc;
		initCentrosDeCostos();
		initSalariosPorCC();
		initSalariosDistribuidosEnCCPPD();
	}
	
	private void initCentrosDeCostos(){
		centros = new ArrayList<CentroCostos>();
		centros = QueryUtil.getInstance().getCentroCostosByCategoria(Categoria.PRODUCTION_CODE);
	}
	
	public void initSalariosPorCC(){
		this.salariosCCP = new HashMap <CentroCostos,Double>();
		for(CentroCostos cc : centros){
			Double salario = QueryUtil.getInstance().getSalarioByCentroCosto(cc, false);
			salariosCCP.put(cc, salario);
		}
		
		this.salariosCCPPD = new HashMap <CentroCostos,Double>();
	}

	public Map<CentroCostos, Double> getSalariosCCP() {
		return salariosCCP;
	}
	
	public Double getTotalSalariosCC(){
		Double total = 0.;
		for(CentroCostos cc : salariosCCP.keySet()){
			total += salariosCCP.get(cc);
		}
		return total;
	}
	
	public Double getDistributedSalaryForCentroCostos(CentroCostos ccp, CentroCostos ccppd){
		CommandDistribucionEnCCPPDporCC aux = this.ccppdCosto.get(ccp);
		return aux.getDistCCPPD().get(ccppd);
	}
	
	public Double getTotalDistributedSalaryForCentroCostos(CentroCostos ccp){
		CommandDistribucionEnCCPPDporCC aux = this.ccppdCosto.get(ccp);
		return aux.getTotal();
	}
	
	public Double getTotalSalaryForCCPPD(CentroCostos ccppd){
		return this.salariosCCPPD.get(ccppd);
	}
	
	public Map <CentroCostos,Double> getsalariosProductivosYParaProductivos(){
		Map <CentroCostos,Double> salariosProductivosYParaProductivos = new HashMap <CentroCostos,Double>();
		for(CentroCostos cc : salariosCCP.keySet()){
			Double sccp = salariosCCP.get(cc);
			Double sccppd = ccppdCosto.get(cc).getTotal();
			Double total = sccp + sccppd;
			salariosProductivosYParaProductivos.put(cc, total);
		}
		return salariosProductivosYParaProductivos;
	}
	
	private void initSalariosDistribuidosEnCCPPD(){
		
		Map <CentroCostos,Double> costosTotalesCCPPD = costosTotalesCCPP();
		ccppdCosto = new HashMap<CentroCostos, CommandDistribucionEnCCPPDporCC>();
		
		for(CentroCostos cc : salariosCCP.keySet()){
			CommandDistribucionEnCCPPDporCC cde = costosTotalesCCPPDMaquina(cc, costosTotalesCCPPD);
			ccppdCosto.put(cc, cde);
		}
	}
	
	private CommandDistribucionEnCCPPDporCC costosTotalesCCPPDMaquina(CentroCostos maquina, Map <CentroCostos,Double> costosTotalesCCPPD){		
		CommandDistribucionEnCCPPDporCC cde = new CommandDistribucionEnCCPPDporCC();
		Map <CentroCostos,Double> aux = new HashMap<CentroCostos, Double>();
		
		Double costoTotal = 0.0d;
		
		for (CentroCostos cc : costosTotalesCCPPD.keySet()){
			Double totalCuenta = costosTotalesCCPPD.get(cc);
			this.salariosCCPPD.put(cc, totalCuenta);
			
			CriterioDistribucion c = cc.getCriterio();
			
			Double proporcion = getProporcion(c, maquina);
			Double costoCuenta = totalCuenta*proporcion;
			aux.put(cc, costoCuenta);
			costoTotal += costoCuenta;
		}
		cde.setTotal(costoTotal);
		cde.setDistCCPPD(aux);
		return cde;
	}
	
	private Map <CentroCostos,Double> costosTotalesCCPP(){
		Integer categoria = Categoria.SERVICES_CODE;
		Map <CentroCostos,Double> costosTotalesCCPP = new HashMap<CentroCostos, Double>();
		
		List<CentroCostos> paraProductivos = QueryUtil.getInstance().getCentroCostosByCategoria(categoria); 
		
		/*inicializo el mapa*/
		for(CentroCostos cc : paraProductivos){
			costosTotalesCCPP.put(cc, 0.0d);
		}
		
		for(CentroCostos cc : paraProductivos){
			Double totalCuenta = QueryUtil.getInstance().getSalarioByCentroCosto(cc, false);
			costosTotalesCCPP.put(cc,totalCuenta);
		}
		
		return costosTotalesCCPP;
	}
	
	private Double getProporcion(CriterioDistribucion c, CentroCostos cc){
		Double proporcion = 0.0d;
		try {
			proporcion = matriz_proporcion_criterio_cc.get(c).get(cc);
		} catch (Exception e) {
		}
		return proporcion;
	}
	
	public Map<CentroCostos, Double> getSalariosCCPPD() {
		return salariosCCPPD;
	}

	private class CommandDistribucionEnCCPPDporCC{
		private Map <CentroCostos,Double> distCCPPD;
		private Double total = 0.;
		
		public CommandDistribucionEnCCPPDporCC(){
			this.distCCPPD = new HashMap <CentroCostos,Double>();
		}

		public Map<CentroCostos, Double> getDistCCPPD() {
			return distCCPPD;
		}

		public void setDistCCPPD(Map<CentroCostos, Double> distCCPPD) {
			this.distCCPPD = distCCPPD;
		}

		public Double getTotal() {
			return total;
		}

		public void setTotal(Double total) {
			this.total = total;
		}

		@Override
		public String toString() {
			return "CommandDistribucionEnCCPPDporCC [distCCPPD=" + distCCPPD
					+ ", total=" + total + "]";
		}
		
		
	}
}
